package com.sinosoft.common.db;

import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.util.List;

import org.nutz.dao.Cnd;
import org.nutz.dao.Dao;
import org.nutz.dao.Sqls;
import org.nutz.dao.entity.Entity;
import org.nutz.dao.entity.annotation.PK;
import org.nutz.dao.impl.ext.LazyNutDao;
import org.nutz.dao.sql.Criteria;
import org.nutz.dao.sql.Sql;
import org.nutz.json.Json;
import org.nutz.lang.Mirror;
import org.nutz.log.Log;
import org.nutz.log.Logs;
import org.nutz.mvc.ActionContext;

import com.sinosoft.common.bean.BaseCondition;
import com.sinosoft.common.datatype.DateTime;
import com.sinosoft.common.util.BeanUtil;
import com.sinosoft.common.util.Constans;
import com.sinosoft.common.util.PowerUtil;
import com.sinosoft.domain.base.BaseUser;
/**
 * 
 * @author unhappydepig 
 * @mail yqw8912@163.com
 * @time 2015-4-27 下午4:22:11
 */
public class DaoUtil {
	private Log log = Logs.get();
	/**
	 * 上下文路径
	 */
	private ActionContext context = null;
	/**
	 * 数据操作对象
	 */
	private Dao dao = null;
	/**
	 * 权限控制
	 */
	private  String[] comArray = null;
	/**
	 * 权限标识位
	 */
	private static final  String comFlag = "comId";
	/**
	 * 权限标识位
	 */
	private static final  String userFlag = "createBy";
	/**
	 * 是否权限控制
	 */
	private  boolean powerFlag = false;
	/**
	 * 是否权限控制
	 */
	private  int powerLevel = Constans.P_SELF_NEXY_SUB;
	
	public  DaoUtil(Dao dao) {
		this.dao = dao;
	}

	public DaoUtil(){
	}
	
	/**
	 * 查询结果列表
	 * @param t
	 * @param baseConditionDto
	 * @return
	 */
	public <T> List<T> queryList(T t, BaseCondition baseCondition) {
		
		Class c = t.getClass();	
		if(null==baseCondition){
			baseCondition = new BaseCondition();
		}
		Criteria contion =  this.createContion(t, Constans.Q_EQU);
		if(null!=baseCondition.getOrderField()&&!"".equals(baseCondition.getOrderField())){
			if(null!=baseCondition.getOrderDirection()&&"desc".equals(baseCondition.getOrderDirection())){
				contion.getOrderBy().desc(baseCondition.getOrderField());
			}else{
				contion.getOrderBy().asc(baseCondition.getOrderField());
			}
		}
		
		List<T> queryList = dao.query(c, contion, baseCondition);//默认使用全局匹配
		baseCondition.setRecordCount(dao.count(c, contion));
		return queryList;
	}		
	/**
	 * 查询结果列表
	 * @param t
	 * @param baseConditionDto
	 * @return
	 */
	public <T> List<T> queryList(T t) {
		Class c = t.getClass();	
		List<T> queryList = dao.query(c, this.createContion(t, Constans.Q_EQU));//默认使用全局匹配
		return queryList;
	}		
    /**
     * 增加记录,成功返回对象,失败返回null
     * @param dao
     * @param t
     * @return
     */
    public <T> T add( T t) {
        T rt;
        try { 	
            rt = dao.insert(getAddDto(t));
        } catch (Exception e) {
        	log.error(e);       
            return null;
        }
        return rt;
    }
    /**
     * 修改一条数据
     * @param dao
     * @param t
     * @return
     */
    public <T> boolean update(T t) {    	     	
        return dao.updateIgnoreNull(getEditDto(t)) == 1;
    } 	
    /**
     * 根据字符串列名查询一个对象
     *
     * @param dao
     * @param obj
     * @param colname
     * @param name
     * @return
     */
    public <T> T detailByPK(Class<T> obj,String pk) {
        T t;
        try {
            t = dao.fetch(obj, this.getPKContion(obj, pk));
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
        return t;
    }
	/**
	 * 查询结果列表
	 * @param t
	 * @param baseConditionDto
	 * @return
	 */
	public <T> T detailByContion(T t) {
		List<T> objectList = this.queryList(t,new BaseCondition(1, 1));
		if(null!=objectList&&objectList.size()>0){
			return objectList.get(0);
		}	
		return null;
	}	    
    /**
     * 按照主键删除
     * @param obj
     * @param pk
     * @return
     */
	public <T> int deleteByPK(Class<T> obj,String pk) {
		return dao.clear(obj, this.getPKContion(obj, pk));
	}    
	public <T> int delete(Class<T> obj, Cnd cnd) {
		return dao.clear(obj, cnd);
	}
	/**
	 * 根据入参生成查询条件
	 * @param <T>
	 * @param <T>
	 * @param dataTableInput
	 * @param contionLevel 查询条件级别 设计用来控制是否全局模糊查询  0 模糊搜索 1:完全匹配搜索
	 * @return
	 */
	public  <T> Criteria createContion(T obj, int contionLevel) {
		
		Mirror<?> mirror = Mirror.me(obj.getClass());
		Field[] fields = mirror.getFields();
		Criteria cri = Cnd.cri() ;
		boolean haveComFlag = false;
		boolean haveUserFlag = false;
		if(fields.length>0){
			for(int i=0;i<fields.length;i++){
				if(!BeanUtil.getDbFlag(obj,fields[i])){//如果判断一下当前属性是否包含Column注解如包含则说明是数据库中存在的属性
					continue;
				}
				fields[i].getDeclaredAnnotations();
				String fieldName = fields[i].getName();
				if(comFlag.equals(fieldName)){
					haveComFlag = true;
				}
				if(userFlag.equals(fieldName)){
					haveUserFlag = true;
				}
				Object v = null;
				try {
					v = mirror.getValue(obj, mirror.getField(fieldName));
				} catch (Exception e) {
					e.printStackTrace();
				}
				if(null!=v&&!"".equals(v.toString())){
					if((v.getClass().getName().equals(Integer.class.getName())) &&0==Integer.parseInt(v.toString())){
						continue;
					}					
					if(Constans.Q_EQU==contionLevel){
						cri.where().andEquals(fieldName, v);
					}else if(Constans.Q_LIKE==contionLevel){
						cri.where().andLike(fieldName,v.toString());
					}
				}
				
			}
		}
		if(powerFlag&&(haveComFlag||haveUserFlag)){
			if(null!=comArray&&comArray.length>0){
				if(powerLevel==Constans.P_USER){
					cri.where().andIn(userFlag, comArray);
				}else{
					cri.where().andIn(comFlag, comArray);
				}
			}else{
				cri.where().and("1", "=","2");	
			}
		}
		
		return cri;
	}	   
	public void setContext(ActionContext context) {		
		this.context = context;
	}
	public void setDao(Dao dao) {
		this.dao = dao;
	}
	public ActionContext getContext() {
		return context;
	}
	public Dao getDao() {
		return dao;
	}
	
	/**
	 * 根据对象及前端传过来的条件获取查询条件
	 * @param type
	 * @param id
	 * @return
	 */
	protected <T> Cnd getPKContion(Class<T>  type,String id){
		Cnd contion= null;
        Mirror<?> mirror = Mirror.me(type);
        PK annPK = mirror.getAnnotation(PK.class);
        String[] colNameArray = annPK.value();
        String[] colValArray = id.split(Constans.PK_SEP);
        if(null!=colNameArray&&colNameArray.length>=0){
        	if(colValArray.length==colValArray.length){
        		contion = Cnd.where(colNameArray[0], "=",colValArray[0]);
        		for(int i=1;i<colValArray.length;i++){
        			contion.and(colNameArray[i], "=",colValArray[i]);	
        		}
        		return contion;
        	}
            return Cnd.where("1", "=", "2");	
        }
        return Cnd.where("1", "=", "2");        
	}
	/**
	 * 新怎的时候赋部分默认值
	 * @param t
	 * @return
	 */
	public <T> T getAddDto( T t){
		Object id = BeanUtil.getValue(t, "PK");
		if(null==id||"".equals(id)){
			BeanUtil.setValue(t, "PK", getPk(t));
		}		
		BeanUtil.setValue(t, "createBy", getUserID());
		BeanUtil.setValue(t, "createTime", DateTime.current());
		BeanUtil.setValue(t, "updateBy", getUserID());   
		BeanUtil.setValue(t, "updateTime", DateTime.current());     		
		return t;
	}
	/**
	 * 更新的时候赋部分默认值
	 * @param t
	 * @return
	 */
	public <T> T getEditDto( T t){
		BeanUtil.setValue(t, "updateBy", getUserID());   
		BeanUtil.setValue(t, "updateTime", DateTime.current());     		
		return t;
	}	
	/**
	 *  获取用户ID
	 * @return
	 */
	public String getUserID(){
		String userId ="";
		if(null!=context&&null!=context.getRequest()){
			userId = context.getRequest().getRemoteAddr();
		}
		if(null!=context.getRequest().getSession()&&null!=context.getRequest().getSession().getAttribute("userSession")){
			BaseUser user=  (BaseUser) context.getRequest().getSession().getAttribute("userSession");
			userId = user.getUserId();
		}
		return userId;	
	}
	public <T> String getPk(T t){
		return ""+DateTime.current().getTime();
	}
    /**
     * 自定义SQL，返回表对象
     *
     * @param dao
     * @param obj
     * @param sql
     * @return
     */
    public <T> List<T> list(Class<T> obj, Sql sql) {
        Entity<T> entity = dao.getEntity(obj);
        sql.setEntity(entity);
        sql.setCallback(Sqls.callback.entities());
        dao.execute(sql);
        return sql.getList(obj);
    }
	public String[] getComArray() {
		return comArray;
	}
	public void setComArray(String[] comArray) {		
		this.powerFlag = true;
		this.comArray = comArray;
	}
	public boolean isPowerFlag() {
		return powerFlag;
	}
	public void setPowerFlag(boolean powerFlag) {
		String sessionId = context.getRequest().getSession().getId();
		this.comArray = PowerUtil.getComArrayBySessionId(sessionId,powerLevel);
		this.powerFlag = powerFlag;
	}
	public void setPowerLevel(int powerLevel) {
		this.powerLevel = powerLevel;
		setPowerFlag(true);
	}	
	
}
